use std::os::macos::raw::stat;

use crate::{
    app_state::AppState,
    errors::error::AppError,
    models::{
        response::{Response, ResponseFailed, ResponseSuccessWithData},
        user::{UserSaveDTO, UserSigninDTO},
    },
    services::user_services::UserService,
};
use axum::{
    extract::{Path, State},
    response::IntoResponse,
    Json,
};

#[utoipa::path(
  post,
  path = "/api/signin",
  request_body = UserSaveDTO,
  responses(
      (status = 200, description = "User signed in successfully", body = Response<String>),
      (status = 400, description = "Bad request"),
      (status = 500, description = "Internal server error")
  )
)]
/// Sign in a user with email and password.
pub async fn signup_handler(
    State(state): State<AppState>,
    Json(dto): Json<UserSaveDTO>,
) -> Result<impl IntoResponse, AppError> {
    let user = UserService::save(dto, state.clone()).await?;
    let token = state.ek.sign(user)?;
    Ok(Response::success(token))
}

#[utoipa::path(
  post,
  path = "/api/signin",
  request_body = UserSigninDTO,
  responses(
      (status = 200, description = "User signed in successfully", body = Response<String>),
      (status = 400, description = "Bad request"),
      (status = 500, description = "Internal server error")
  )
)]
pub async fn signin_handler(
    State(state): State<AppState>,
    Json(dto): Json<UserSigninDTO>,
) -> Result<impl IntoResponse, AppError> {
    let user_opt = UserService::find_by_email(&dto.email, &dto.password, state.clone()).await?;
    match user_opt {
        Some(user) => {
            let token = state.ek.sign(user)?;
            Ok(Response::<String>::success(token))
        }
        None => {
            // Ok(Response::<()>::failed(400, "Bad Request".to_string()).into_response())
            let res = Response::<String>::failed(400, "Not Found user ".to_string());
            return Ok(res);
        }
    }
}
/*************  ✨ Codeium Command ⭐  *************/
/// Retrieve a user by their ID.
///
/// This endpoint allows you to fetch user details using a unique user ID.
/// It returns a success response with the user information if found, otherwise,
/// it will return an error response.
///
/// - **URL:** `/api/users/{id}`
/// - **Method:** `POST`
///
/// # Parameters
/// - `id`: The unique identifier of the user to be retrieved.
///
/// # Responses
/// - `200`: User found successfully, returns user details.
/// - `400`: Bad request, likely due to invalid input.
/// - `500`: Internal server error, indicating a problem with the server.

/******  0f52afc9-5058-4e68-a765-b94500184d33  *******/
#[utoipa::path(
  post,
  path = "/api/users/:{id}",
  request_body = u32,
  responses(
      (status = 200, description = "User signed in successfully", body = Response<String>),
      (status = 400, description = "Bad request"),
      (status = 500, description = "Internal server error")
  )
)]
pub async fn get_user(
    State(state): State<AppState>,
    Path(id): Path<u64>,
) -> Result<impl IntoResponse, AppError> {
    let user = UserService::find_by_id(id, &state).await?;
    Ok(Response::success(user))
}
